package com.llbnk.srb.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.llbnk.srb.core.enums.BorrowerStatusEnum;
import com.llbnk.srb.core.enums.IntegralEnum;
import com.llbnk.srb.core.mapper.BorrowerAttachMapper;
import com.llbnk.srb.core.mapper.UserInfoMapper;
import com.llbnk.srb.core.mapper.UserIntegralMapper;
import com.llbnk.srb.core.pojo.entity.Borrower;
import com.llbnk.srb.core.mapper.BorrowerMapper;
import com.llbnk.srb.core.pojo.entity.BorrowerAttach;
import com.llbnk.srb.core.pojo.entity.UserInfo;
import com.llbnk.srb.core.pojo.entity.UserIntegral;
import com.llbnk.srb.core.pojo.vo.BorrowerApprovalVO;
import com.llbnk.srb.core.pojo.vo.BorrowerAttachVO;
import com.llbnk.srb.core.pojo.vo.BorrowerDetailVO;
import com.llbnk.srb.core.pojo.vo.BorrowerVO;
import com.llbnk.srb.core.service.BorrowerAttachService;
import com.llbnk.srb.core.service.BorrowerService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.llbnk.srb.core.service.DictService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 * 借款人 服务实现类
 * </p>
 *
 * @author llbnk
 * @since 2022-04-07
 */
@Service
public class BorrowerServiceImpl extends ServiceImpl<BorrowerMapper, Borrower> implements BorrowerService {

    @Resource
    private UserInfoMapper userInfoMapper;

    //BorrowerAttach这是一个专门存放附件（图片）信息的一个类
    @Resource
    private BorrowerAttachMapper borrowerAttachMapper;

    //getBorrowerDetailVOById方法需要把数据字典的序号变成对应的名字
    @Resource
    private DictService dictService;

    //getBorrowerDetailVOById方法中需要把附件的格式从borrowAttach变成borrowerDetailVO
    @Resource
    private BorrowerAttachService borrowerAttachService;

    //approval方法中将积分信息插入到积分表中
    @Resource
    private UserIntegralMapper userIntegralMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveBorrowerVOByUserId(BorrowerVO borrowerVO, Long userId) {

        //获取用户的基本信息
        UserInfo userInfo = userInfoMapper.selectById(userId);

        //将网页填写的信息都按照定义实体类Borrower的格式拷贝一份到borrow对象中
        Borrower borrower = new Borrower();
        BeanUtils.copyProperties(borrowerVO,borrower);

        //设置一些其他没有的参数比如说id 姓名....
        //注意网页借款人信息认证（http://localhost:3000/user/borrower）中
        //个人基本信息并没有姓名身份证号什么的 ，有的是联系人信息（妻子，家人）
        //身份证也是上传的图片所以我们不可能读取图片得到信息的
        //所以我们需要从user_info这张表中提取出来这些必要信息填入borrower对象中
        borrower.setUserId(userId);
        borrower.setName(userInfo.getName());
        borrower.setIdCard(userInfo.getIdCard());
        borrower.setMobile(userInfo.getMobile());
        //只要填写数据了就会将借款人的状态变为认证中
        borrower.setStatus(BorrowerStatusEnum.AUTH_RUN.getStatus());
        baseMapper.insert(borrower);

        //保存附件
        //图片的格式就是List格式从前端传回来 可以在F12的vue中的data中borrowerAttachList查看
        //前端的格式如下
        //imageName:"正面1.jpg"
        //imageType:"idCard1"
        //imageUrl:"https://srb-flie-srbk.oss-cn-beijing.aliyuncs.com/idCard1/2022/04/17/4d16d9c0-b738-45ac-9a12-75612dceb544.jpg"
        List<BorrowerAttach> borrowerAttachList = borrowerVO.getBorrowerAttachList();
        borrowerAttachList.forEach(borrowerAttach -> {
            borrowerAttach.setBorrowerId(borrower.getId());
            //将这个图片信息插入数据库中
            borrowerAttachMapper.insert(borrowerAttach);
        });

        //因为是借款会员所以在user_info中做了一个冗余字段borrow_auth_status
        //我们也需要将这个字段修改做到和borrower_attach信息同步
        //更新user_info中的借款人认证状态
        userInfo.setBorrowAuthStatus(BorrowerStatusEnum.AUTH_RUN.getStatus());
        userInfoMapper.updateById(userInfo);

    }

    @Override
    public Integer getStatusByUserId(Long userId) {

        QueryWrapper<Borrower> borrowerQueryWrapper = new QueryWrapper<>();
        borrowerQueryWrapper.select("status").eq("user_id",userId);
        //selectObjs专门是用来查询一行记录的一个字段专门的方法  List<Object>存的值就是status这一个字段
        List<Object> objects = baseMapper.selectObjs(borrowerQueryWrapper);

        //因为我们通过id查询status只可能有一个数据，或者一个都没有
        //如果list中一条数据都没有说明借款人还没有填写表单呢，所以我们需要向用户显示填写认证页面
        if(objects.size() == 0){
            //没认证就返回没认证状态，让前端知道应该展示填写借款人信息页面
            return BorrowerStatusEnum.NO_AUTH.getStatus();
        }
        //如果填写过了就显示“您的认证申请已成功提交，请耐心等待”的等待页面
        Integer status = (Integer) objects.get(0);
        return status;

    }

    @Override
    public IPage<Borrower> listPage(Page<Borrower> pageParam, String keyword) {

        //如果没有查询条件的话就正常分页
        if(StringUtils.isBlank(keyword)){
            return baseMapper.selectPage(pageParam,null);
        }

        //如果关键词不为null，我们就进行模糊查询,然后按照从新往旧记录方法排序
        QueryWrapper<Borrower> borrowerQueryWrapper = new QueryWrapper<>();
        borrowerQueryWrapper.like("name",keyword)
                .or()
                .eq("id_card",keyword)
                .or()
                .eq("mobile",keyword)
                .orderByDesc("id");

        return baseMapper.selectPage(pageParam,borrowerQueryWrapper);
    }

    /**
     * 向borrowerDetailVO对象填入数据，大部分可以直接通过borrow对象填写（可看上面方法saveBorrowerVOByUserId
     * 当借款人绑定信息之后，把信息都填入borrow表中）
     * 还有一些信息在borrow表中存放的是数据字典中的序号
     * 我们要转换成对象的字符串，比如说男，女，硕士，本科，IT，律师等等
     * @param id 传递进来是borrower的id
     * @return
     */
    @Override
    public BorrowerDetailVO getBorrowerDetailVOById(Long id) {

        //获取借款人信息
        Borrower borrower = baseMapper.selectById(id);

        //填充基本借款人信息
        BorrowerDetailVO borrowerDetailVO = new BorrowerDetailVO();
        BeanUtils.copyProperties(borrower,borrowerDetailVO);

        //将数据字典中的下拉列表转换为对应的字符串
        //婚否
        borrowerDetailVO.setMarry(borrower.getMarry()?"是":"否");
        //性别
        borrowerDetailVO.setSex(borrower.getSex() == 1?"男":"女");
        //下拉列表 这个地方就是通过数据字典中对应的id得到他的name
        //下面这几个数据本质都差不多所以我们可以在DictService中编写方法
        //就通过给父节点DictCode （industry，salary... ）和小类的id值返回这个小类的名字
        //这个地方没有使用用途和学历主要原因是因为审核让填写的数据中没有这两项（可以看borroww表）
        borrowerDetailVO.setEducation(
                dictService.getNameByParentDictCodeAndValue("education",borrower.getEducation())
        );
        borrowerDetailVO.setIndustry(
                dictService.getNameByParentDictCodeAndValue("industry",borrower.getIndustry())
        );
        borrowerDetailVO.setIncome(
                dictService.getNameByParentDictCodeAndValue("income", borrower.getIncome())
        );
        borrowerDetailVO.setReturnSource(
                dictService.getNameByParentDictCodeAndValue("returnSource", borrower.getReturnSource())
        );
        borrowerDetailVO.setContactsRelation(
                dictService.getNameByParentDictCodeAndValue("relation",borrower.getContactsRelation())
        );

        //审批状态 borrow表中的status是一个整型，但是borrowerDetailVO要的是一个字符串
        //所以需要借助BorrowerStatusEnum来转换
        String status = BorrowerStatusEnum.getMsgByStatus(borrower.getStatus());
        borrowerDetailVO.setStatus(status);

        //附件列表borrower_attach中存放附件（图片）borrow的id和borrower_attach的borrower_id相同
        //所以我们直接调用BorrowerAttachService中的
        List<BorrowerAttachVO> borrowerAttachVOList = borrowerAttachService.selectBorrowerAttachVOList(id);
        borrowerDetailVO.setBorrowerAttachVOList(borrowerAttachVOList);

        return borrowerDetailVO;

    }

    /**
     * 从前端传回来的borrowerApprovalVO对象包含审核是否通过，积分计算，附件信息是否正确，把这些都写在borrow表中
     * 更新了borrower表的状态status
     * 插入userIntegral表中新的积分数据
     * 更新userInfo表中的积分字段和状态字段
     * @param borrowerApprovalVO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void approval(BorrowerApprovalVO borrowerApprovalVO) {

        //获取借款额度申请id
        Long borrowerId = borrowerApprovalVO.getBorrowerId();

        //获取借款额度申请对象
        Borrower borrower = baseMapper.selectById(borrowerId);

        //设置审核状态（通过还是不通过）从前端传回来的
        borrower.setStatus(borrowerApprovalVO.getStatus());
        baseMapper.updateById(borrower);

        //获取用户id
        Long userId = borrower.getUserId();

        //获取用户对象（这个是用来赋值整个用户应该获得多少积分的）
        //这个用户的积分不是简简单单赋值就行了，比如原来用户里面有积分，你在计算新积分
        //应该是你之前的积分+基本信息积分+房产积分+车辆积分+身份证积分
        UserInfo userInfo = userInfoMapper.selectById(userId);

        //用户的原始积分
        Integer integral = userInfo.getIntegral();

        //计算基本信息积分(从前端传递回来的积分（积分是由管理员自己写的））
        //UserIntegral表是专门存放和积分相关的信息的表
        UserIntegral userIntegral = new UserIntegral();
        userIntegral.setUserId(userId);
        userIntegral.setIntegral(borrowerApprovalVO.getInfoIntegral());
        userIntegral.setContent("借款人基本信息");
        userIntegralMapper.insert(userIntegral);
        //更新积分
        int currentIntegral = integral+ borrowerApprovalVO.getInfoIntegral();

        //身份证积分
        //判断身份证是否审核通过（审核通过采用积分）
        if(borrowerApprovalVO.getIsIdCardOk()){
            userIntegral = new UserIntegral();
            userIntegral.setUserId(userId);
            //IntegralEnum.BORROWER_IDCARD.getIntegral() 身份证通过30积分
            userIntegral.setIntegral(IntegralEnum.BORROWER_IDCARD.getIntegral());
            userIntegral.setContent(IntegralEnum.BORROWER_IDCARD.getMsg());
            userIntegralMapper.insert(userIntegral);
            //更新积分
            currentIntegral += IntegralEnum.BORROWER_IDCARD.getIntegral();
        }

        //房产信息
        if(borrowerApprovalVO.getIsHouseOk()) {
            userIntegral = new UserIntegral();
            userIntegral.setUserId(userId);
            userIntegral.setIntegral(IntegralEnum.BORROWER_HOUSE.getIntegral());
            userIntegral.setContent(IntegralEnum.BORROWER_HOUSE.getMsg());
            userIntegralMapper.insert(userIntegral);
            currentIntegral += IntegralEnum.BORROWER_HOUSE.getIntegral();
        }

        //车辆信息
        if(borrowerApprovalVO.getIsCarOk()) { ;
            userIntegral = new UserIntegral();
            userIntegral.setUserId(userId);
            userIntegral.setIntegral(IntegralEnum.BORROWER_CAR.getIntegral());
            userIntegral.setContent(IntegralEnum.BORROWER_CAR.getMsg());
            userIntegralMapper.insert(userIntegral);
            currentIntegral += IntegralEnum.BORROWER_CAR.getIntegral();
        }

        //设置用户总积分
        userInfo.setIntegral(currentIntegral);

        //修改审核状态
        userInfo.setBorrowAuthStatus(borrowerApprovalVO.getStatus());

        //更新userInfo表
        userInfoMapper.updateById(userInfo);
    }
}
